﻿namespace HySoft.Cash.BaseClass
{
    using System;
    using System.Collections;
    using System.IO;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Text;

    public class MailSender
    {
        private ArrayList attachments = new ArrayList();
        private string body = "";
        private string encoding = "8bit";
        private string from = "";
        private string fromName = "";
        private string htmlBody = "";
        private bool isHtml = false;
        private string languageEncoding = "GB2312";
        private string password = "";
        private int port = 0x19;
        private int priority = 3;
        private string server = "";
        private string subject = "";
        private string to = "";
        private string toName = "";
        private string userName = "";

        protected bool Command(NetworkStream netStream, string command, string state)
        {
            bool flag = false;
            try
            {
                this.WriteString(netStream, command);
                if (this.ReadString(netStream).IndexOf(state) != -1)
                {
                    flag = true;
                }
            }
            catch (Exception)
            {
            }
            return flag;
        }

        protected string ReadString(NetworkStream netStream)
        {
            string str = null;
            byte[] buffer = new byte[0x400];
            if (netStream.Read(buffer, 0, buffer.Length) > 0)
            {
                str = Encoding.Default.GetString(buffer);
            }
            return str;
        }

        public void SendMail()
        {
            TcpClient client = null;
            try
            {
                client = new TcpClient(this.server, this.port);
            }
            catch (Exception)
            {
                throw new Exception("无法连接服务器");
            }
            this.ReadString(client.GetStream());
            if (!this.Command(client.GetStream(), "EHLO Localhost", "250"))
            {
                throw new Exception("登陆阶段失败");
            }
            if (this.userName != "")
            {
                if (!this.Command(client.GetStream(), "AUTH LOGIN", "334"))
                {
                    throw new Exception("身份验证阶段失败");
                }
                string command = this.ToBase64(this.userName);
                if (!this.Command(client.GetStream(), command, "334"))
                {
                    throw new Exception("身份验证阶段失败");
                }
                string str2 = this.ToBase64(this.password);
                if (!this.Command(client.GetStream(), str2, "235"))
                {
                    throw new Exception("身份验证阶段失败");
                }
            }
            this.WriteString(client.GetStream(), "mail From: " + this.from);
            this.WriteString(client.GetStream(), "rcpt to: " + this.to);
            this.WriteString(client.GetStream(), "data");
            this.WriteString(client.GetStream(), "Date: " + DateTime.Now);
            this.WriteString(client.GetStream(), "From: " + this.fromName + "<" + this.from + ">");
            this.WriteString(client.GetStream(), "Subject: " + this.subject);
            this.WriteString(client.GetStream(), "To:" + this.toName + "<" + this.to + ">");
            this.WriteString(client.GetStream(), "Content-Type: multipart/mixed; boundary=\"unique-boundary-1\"");
            this.WriteString(client.GetStream(), "Reply-To:" + this.from);
            this.WriteString(client.GetStream(), "X-Priority:" + this.priority);
            this.WriteString(client.GetStream(), "MIME-Version:1.0");
            this.WriteString(client.GetStream(), "Content-Transfer-Encoding:" + this.encoding);
            this.WriteString(client.GetStream(), "X-Mailer:JcPersonal.Utility.MailSender");
            this.WriteString(client.GetStream(), "");
            this.WriteString(client.GetStream(), this.ToBase64("This is a multi-part message in MIME format."));
            this.WriteString(client.GetStream(), "");
            this.WriteString(client.GetStream(), "--unique-boundary-1");
            this.WriteString(client.GetStream(), "Content-Type: multipart/alternative;Boundary=\"unique-boundary-2\"");
            this.WriteString(client.GetStream(), "");
            if (!this.isHtml)
            {
                this.WriteString(client.GetStream(), "--unique-boundary-2");
                this.WriteString(client.GetStream(), "Content-Type: text/plain;charset=" + this.languageEncoding);
                this.WriteString(client.GetStream(), "Content-Transfer-Encoding:" + this.encoding);
                this.WriteString(client.GetStream(), "");
                this.WriteString(client.GetStream(), this.body);
                this.WriteString(client.GetStream(), "");
                this.WriteString(client.GetStream(), "--unique-boundary-2--");
                this.WriteString(client.GetStream(), "");
            }
            else
            {
                this.WriteString(client.GetStream(), "--unique-boundary-2");
                this.WriteString(client.GetStream(), "Content-Type: text/html;charset=" + this.languageEncoding);
                this.WriteString(client.GetStream(), "Content-Transfer-Encoding:" + this.encoding);
                this.WriteString(client.GetStream(), "");
                this.WriteString(client.GetStream(), this.htmlBody);
                this.WriteString(client.GetStream(), "");
                this.WriteString(client.GetStream(), "--unique-boundary-2--");
                this.WriteString(client.GetStream(), "");
            }
            for (int i = 0; i < this.attachments.Count; i++)
            {
                this.WriteString(client.GetStream(), "--unique-boundary-1");
                AttachmentInfo info = (AttachmentInfo) this.attachments[i];
                this.WriteString(client.GetStream(), "Content-Type: application/octet-stream;name=\"" + info.FileName + "\"");
                this.WriteString(client.GetStream(), "Content-Transfer-Encoding: base64");
                info = (AttachmentInfo) this.attachments[i];
                this.WriteString(client.GetStream(), "Content-Disposition:attachment;filename=\"" + info.FileName + "\"");
                this.WriteString(client.GetStream(), "");
                info = (AttachmentInfo) this.attachments[i];
                this.WriteString(client.GetStream(), info.Bytes);
                this.WriteString(client.GetStream(), "");
            }
            this.Command(client.GetStream(), ".", "250");
            client.Close();
        }

        protected string ToBase64(string str)
        {
            try
            {
                str = Convert.ToBase64String(Encoding.Default.GetBytes(str.ToCharArray()));
            }
            catch (Exception)
            {
            }
            return str;
        }

        protected void WriteString(NetworkStream netStream, string str)
        {
            str = str + "\r\n";
            byte[] bytes = Encoding.GetEncoding(this.languageEncoding).GetBytes(str.ToCharArray());
            int offset = 0;
            int length = bytes.Length;
            int num3 = 0;
            int num4 = 0x4b;
            int count = num4;
            try
            {
                if (length > 0x4b)
                {
                    if (((length / num4) * num4) < length)
                    {
                        num3 = (length / num4) + 1;
                    }
                    else
                    {
                        num3 = length / num4;
                    }
                    for (int i = 0; i < num3; i++)
                    {
                        offset = i * num4;
                        if (i == (num3 - 1))
                        {
                            count = length - (i * num4);
                        }
                        netStream.Write(bytes, offset, count);
                    }
                }
                else
                {
                    netStream.Write(bytes, 0, bytes.Length);
                }
            }
            catch (Exception)
            {
            }
        }

        public IList Attachments
        {
            get
            {
                return this.attachments;
            }
        }

        public string Body
        {
            get
            {
                return this.body;
            }
            set
            {
                if (value != this.body)
                {
                    this.body = value;
                }
            }
        }

        public string From
        {
            get
            {
                return this.from;
            }
            set
            {
                if (value != this.from)
                {
                    this.from = value;
                }
            }
        }

        public string FromName
        {
            get
            {
                return this.fromName;
            }
            set
            {
                if (value != this.fromName)
                {
                    this.fromName = value;
                }
            }
        }

        public string HtmlBody
        {
            get
            {
                return this.htmlBody;
            }
            set
            {
                if (value != this.htmlBody)
                {
                    this.htmlBody = value;
                }
            }
        }

        public bool IsHtml
        {
            get
            {
                return this.isHtml;
            }
            set
            {
                if (value != this.isHtml)
                {
                    this.isHtml = value;
                }
            }
        }

        public string LanguageEncoding
        {
            get
            {
                return this.languageEncoding;
            }
            set
            {
                if (value != this.languageEncoding)
                {
                    this.languageEncoding = value;
                }
            }
        }

        public string MailEncoding
        {
            get
            {
                return this.encoding;
            }
            set
            {
                if (value != this.encoding)
                {
                    this.encoding = value;
                }
            }
        }

        public string Password
        {
            get
            {
                return this.password;
            }
            set
            {
                if (value != this.password)
                {
                    this.password = value;
                }
            }
        }

        public int Port
        {
            get
            {
                return this.port;
            }
            set
            {
                if (value != this.port)
                {
                    this.port = value;
                }
            }
        }

        public int Priority
        {
            get
            {
                return this.priority;
            }
            set
            {
                if (value != this.priority)
                {
                    this.priority = value;
                }
            }
        }

        public string Server
        {
            get
            {
                return this.server;
            }
            set
            {
                if (value != this.server)
                {
                    this.server = value;
                }
            }
        }

        public string Subject
        {
            get
            {
                return this.subject;
            }
            set
            {
                if (value != this.subject)
                {
                    this.subject = value;
                }
            }
        }

        public string To
        {
            get
            {
                return this.to;
            }
            set
            {
                if (value != this.to)
                {
                    this.to = value;
                }
            }
        }

        public string ToName
        {
            get
            {
                return this.toName;
            }
            set
            {
                if (value != this.toName)
                {
                    this.toName = value;
                }
            }
        }

        public string UserName
        {
            get
            {
                return this.userName;
            }
            set
            {
                if (value != this.userName)
                {
                    this.userName = value;
                }
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct AttachmentInfo
        {
            private string fileName;
            private string bytes;
            public string FileName
            {
                get
                {
                    return this.fileName;
                }
                set
                {
                    this.fileName = Path.GetFileName(value);
                }
            }
            public string Bytes
            {
                get
                {
                    return this.bytes;
                }
                set
                {
                    if (value != this.bytes)
                    {
                        this.bytes = value;
                    }
                }
            }
            public AttachmentInfo(string ifileName, Stream stream)
            {
                this.fileName = Path.GetFileName(ifileName);
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, (int) stream.Length);
                this.bytes = Convert.ToBase64String(buffer);
            }

            public AttachmentInfo(string ifileName, byte[] ibytes)
            {
                this.fileName = Path.GetFileName(ifileName);
                this.bytes = Convert.ToBase64String(ibytes);
            }

            public AttachmentInfo(string path)
            {
                this.fileName = Path.GetFileName(path);
                FileStream stream = new FileStream(path, FileMode.Open);
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, (int) stream.Length);
                this.bytes = Convert.ToBase64String(buffer);
                stream.Close();
            }
        }
    }
}

